/*!
 * \file UftStraBaseCtx.cpp
 * \project	WonderTrader
 *
 * \author Wesley
 * \date 2020/03/30
 * 
 * \brief UFT策略基础上下文实现文件
 * 
 * \details 实现UFT策略基础上下文的所有功能，包括策略接口的具体实现、
 *          交易回报处理、数据访问、订单管理等核心功能。作为UFT策略
 *          运行的基础环境。
 */
#include "UftStraBaseCtx.h"
#include "WtUftEngine.h"
#include "TraderAdapter.h"
#include "WtHelper.h"

#include "../Includes/WTSContractInfo.hpp"

#include "../Share/decimal.h"

#include "../WTSTools/WTSLogger.h"

#include <rapidjson/document.h>
#include <rapidjson/prettywriter.h>
namespace rj = rapidjson;

USING_NS_WTP;

/*!
 * \brief 生成UFT上下文ID的内联函数
 * \return uint32_t 新的上下文ID
 * 
 * \details 使用原子操作生成唯一的UFT上下文ID，起始值为6000，
 *          确保线程安全和ID唯一性
 */
inline uint32_t makeUftCtxId()
{
	static std::atomic<uint32_t> _auto_context_id{ 6000 };
	return _auto_context_id.fetch_add(1);
}

/*!
 * \brief 构造函数实现
 * \param engine UFT引擎指针
 * \param name 策略上下文名称
 * 
 * \details 初始化UFT策略基础上下文，生成唯一的上下文ID，
 *          建立与UFT引擎的关联关系
 */
UftStraBaseCtx::UftStraBaseCtx(WtUftEngine* engine, const char* name)
	: IUftStraCtx(name)
	, _engine(engine)
{
	_context_id = makeUftCtxId();
}

/*!
 * \brief 析构函数实现
 * 
 * \details 清理UFT策略基础上下文资源，断开与引擎和交易器的连接
 */
UftStraBaseCtx::~UftStraBaseCtx()
{
}

/*!
 * \brief 获取上下文ID实现
 * \return uint32_t 上下文唯一标识
 * 
 * \details 返回策略上下文的唯一标识符
 */
uint32_t UftStraBaseCtx::id()
{
	return _context_id;
}

/*!
 * \brief 设置交易适配器实现
 * \param trader 交易适配器指针
 * 
 * \details 绑定交易适配器，用于处理实际的交易请求和回报
 */
void UftStraBaseCtx::setTrader(TraderAdapter* trader)
{
	_trader = trader;
}

/*!
 * \brief 策略初始化回调实现
 * 
 * \details 默认空实现，派生类可以重写此方法进行策略初始化
 */
void UftStraBaseCtx::on_init()
{

}

/*!
 * \brief Tick数据回调实现
 * \param stdCode 标准合约代码
 * \param newTick 新的Tick数据
 * 
 * \details 默认空实现，派生类需要重写此方法处理Tick数据
 */
void UftStraBaseCtx::on_tick(const char* stdCode, WTSTickData* newTick)
{

}

/*!
 * \brief 委托队列数据回调实现
 * \param stdCode 标准合约代码
 * \param newOrdQue 新的委托队列数据
 * 
 * \details 默认空实现，派生类可以重写此方法处理Level2委托队列数据
 */
void UftStraBaseCtx::on_order_queue(const char* stdCode, WTSOrdQueData* newOrdQue)
{

}

/*!
 * \brief 委托明细数据回调实现
 * \param stdCode 标准合约代码
 * \param newOrdDtl 新的委托明细数据
 * 
 * \details 默认空实现，派生类可以重写此方法处理Level2委托明细数据
 */
void UftStraBaseCtx::on_order_detail(const char* stdCode, WTSOrdDtlData* newOrdDtl)
{

}

/*!
 * \brief 成交明细数据回调实现
 * \param stdCode 标准合约代码
 * \param newTrans 新的成交明细数据
 * 
 * \details 默认空实现，派生类可以重写此方法处理Level2成交明细数据
 */
void UftStraBaseCtx::on_transaction(const char* stdCode, WTSTransData* newTrans)
{

}

/*!
 * \brief K线数据回调实现
 * \param stdCode 标准合约代码
 * \param period K线周期
 * \param times 周期倍数
 * \param newBar 新的K线数据
 * 
 * \details 默认空实现，派生类可以重写此方法处理K线数据更新
 */
void UftStraBaseCtx::on_bar(const char* stdCode, const char* period, uint32_t times, WTSBarStruct* newBar)
{

}

/*!
 * \brief 撤销订单实现
 * \param localid 本地订单ID
 * \return bool 撤单请求是否成功提交
 * 
 * \details 调用交易适配器的撤单方法，返回撤单请求是否成功提交
 */
bool UftStraBaseCtx::stra_cancel(uint32_t localid)
{
	return _trader->cancel(localid);
}

/*!
 * \brief 撤销所有订单实现
 * \param stdCode 标准合约代码
 * \return OrderIDs 被撤销的订单ID列表
 * 
 * \details 撤销指定合约的所有未成交订单。
 *          注释掉的频率检查代码预留给风控模块使用。
 */
OrderIDs UftStraBaseCtx::stra_cancel_all(const char* stdCode)
{
	// 频率检查（预留）
	// if (!_trader->checkCancelLimits(stdCode))
	//     return OrderIDs();

	return _trader->cancelAll(stdCode);
}

/*!
 * \brief 买入下单实现
 * \param stdCode 标准合约代码
 * \param price 下单价格
 * \param qty 下单数量
 * \param flag 下单标志
 * \return OrderIDs 订单ID列表
 * 
 * \details 调用交易适配器的买入方法，最后一个参数false表示非强制平仓
 */
OrderIDs UftStraBaseCtx::stra_buy(const char* stdCode, double price, double qty, int flag /* = 0 */)
{
	return _trader->buy(stdCode, price, qty, flag, false);
}

/*!
 * \brief 卖出下单实现
 * \param stdCode 标准合约代码
 * \param price 下单价格
 * \param qty 下单数量
 * \param flag 下单标志
 * \return OrderIDs 订单ID列表
 * 
 * \details 调用交易适配器的卖出方法，最后一个参数false表示非强制平仓
 */
OrderIDs UftStraBaseCtx::stra_sell(const char* stdCode, double price, double qty, int flag /* = 0 */)
{
	return _trader->sell(stdCode, price, qty, flag, false);
}

/*!
 * \brief 开多仓实现
 * \param stdCode 标准合约代码
 * \param price 下单价格
 * \param qty 下单数量
 * \param flag 下单标志
 * \return uint32_t 本地订单ID
 * 
 * \details 调用交易适配器的开多仓方法
 */
uint32_t UftStraBaseCtx::stra_enter_long(const char* stdCode, double price, double qty, int flag /* = 0 */)
{
	return _trader->openLong(stdCode, price, qty, flag);
}

/*!
 * \brief 平多仓实现
 * \param stdCode 标准合约代码
 * \param price 下单价格
 * \param qty 下单数量
 * \param isToday 是否平今仓
 * \param flag 下单标志
 * \return uint32_t 本地订单ID
 * 
 * \details 调用交易适配器的平多仓方法，支持平今和平昨区分
 */
uint32_t UftStraBaseCtx::stra_exit_long(const char* stdCode, double price, double qty, bool isToday /* = false */, int flag /* = 0 */)
{
	return _trader->closeLong(stdCode, price, qty, isToday, flag);
}

/*!
 * \brief 开空仓实现
 * \param stdCode 标准合约代码
 * \param price 下单价格
 * \param qty 下单数量
 * \param flag 下单标志
 * \return uint32_t 本地订单ID
 * 
 * \details 调用交易适配器的开空仓方法
 */
uint32_t UftStraBaseCtx::stra_enter_short(const char* stdCode, double price, double qty, int flag /* = 0 */)
{
	return _trader->openShort(stdCode, price, qty, flag);
}

/*!
 * \brief 平空仓实现
 * \param stdCode 标准合约代码
 * \param price 下单价格
 * \param qty 下单数量
 * \param isToday 是否平今仓
 * \param flag 下单标志
 * \return uint32_t 本地订单ID
 * 
 * \details 调用交易适配器的平空仓方法，支持平今和平昨区分
 */
uint32_t UftStraBaseCtx::stra_exit_short(const char* stdCode, double price, double qty, bool isToday /* = false */, int flag /* = 0 */)
{
	return _trader->closeShort(stdCode, price, qty, isToday, flag);
}

/*!
 * \brief 获取品种信息实现
 * \param stdCode 标准合约代码
 * \return WTSCommodityInfo* 品种信息指针
 * 
 * \details 通过UFT引擎获取指定合约的品种基础信息
 */
WTSCommodityInfo* UftStraBaseCtx::stra_get_comminfo(const char* stdCode)
{
	return _engine->get_commodity_info(stdCode);
}

/*!
 * \brief 获取K线数据实现
 * \param stdCode 标准合约代码
 * \param period K线周期
 * \param count 获取K线数量
 * \return WTSKlineSlice* K线数据切片
 * 
 * \details 解析K线周期字符串，获取基础周期和倍数，然后通过UFT引擎获取K线数据。
 *          获取成功后自动订阅该合约的Tick数据。
 */
WTSKlineSlice* UftStraBaseCtx::stra_get_bars(const char* stdCode, const char* period, uint32_t count)
{
	std::string basePeriod = "";
	uint32_t times = 1;
	if (strlen(period) > 1)
	{
		// 解析周期字符串，如"m5"解析为基础周期"m"和倍数5
		basePeriod.append(period, 1);
		times = strtoul(period + 1, NULL, 10);
	}
	else
	{
		basePeriod = period;
	}

	WTSKlineSlice* ret = _engine->get_kline_slice(_context_id, stdCode, basePeriod.c_str(), count, times);

	if (ret)
		_engine->sub_tick(id(), stdCode);

	return ret;
}

/*!
 * \brief 获取Tick数据实现
 * \param stdCode 标准合约代码
 * \param count 获取Tick数量
 * \return WTSTickSlice* Tick数据切片
 * 
 * \details 通过UFT引擎获取Tick数据，获取成功后自动订阅该合约的Tick数据
 */
WTSTickSlice* UftStraBaseCtx::stra_get_ticks(const char* stdCode, uint32_t count)
{
	WTSTickSlice* ticks = _engine->get_tick_slice(_context_id, stdCode, count);

	if (ticks)
		_engine->sub_tick(id(), stdCode);
	return ticks;
}

/*!
 * \brief 获取委托明细数据实现
 * \param stdCode 标准合约代码
 * \param count 获取数据数量
 * \return WTSOrdDtlSlice* 委托明细数据切片
 * 
 * \details 通过UFT引擎获取委托明细数据，获取成功后自动订阅该合约的委托明细数据
 */
WTSOrdDtlSlice* UftStraBaseCtx::stra_get_order_detail(const char* stdCode, uint32_t count)
{
	WTSOrdDtlSlice* ret = _engine->get_order_detail_slice(_context_id, stdCode, count);

	if (ret)
		_engine->sub_order_detail(id(), stdCode);
	return ret;
}

/*!
 * \brief 获取委托队列数据实现
 * \param stdCode 标准合约代码
 * \param count 获取数据数量
 * \return WTSOrdQueSlice* 委托队列数据切片
 * 
 * \details 通过UFT引擎获取委托队列数据，获取成功后自动订阅该合约的委托队列数据
 */
WTSOrdQueSlice* UftStraBaseCtx::stra_get_order_queue(const char* stdCode, uint32_t count)
{
	WTSOrdQueSlice* ret = _engine->get_order_queue_slice(_context_id, stdCode, count);

	if (ret)
		_engine->sub_order_queue(id(), stdCode);
	return ret;
}

/*!
 * \brief 获取成交明细数据实现
 * \param stdCode 标准合约代码
 * \param count 获取数据数量
 * \return WTSTransSlice* 成交明细数据切片
 * 
 * \details 通过UFT引擎获取成交明细数据，获取成功后自动订阅该合约的成交明细数据
 */
WTSTransSlice* UftStraBaseCtx::stra_get_transaction(const char* stdCode, uint32_t count)
{
	WTSTransSlice* ret = _engine->get_transaction_slice(_context_id, stdCode, count);

	if (ret)
		_engine->sub_transaction(id(), stdCode);
	return ret;
}

/*!
 * \brief 获取最新Tick数据实现
 * \param stdCode 标准合约代码
 * \return WTSTickData* 最新Tick数据指针
 * 
 * \details 通过UFT引擎获取指定合约的最新Tick数据
 */
WTSTickData* UftStraBaseCtx::stra_get_last_tick(const char* stdCode)
{
	return _engine->get_last_tick(_context_id, stdCode);
}

/*!
 * \brief 订阅Tick数据实现
 * \param stdCode 标准合约代码
 * 
 * \details 通过UFT引擎订阅指定合约的Tick数据，并记录订阅日志
 */
void UftStraBaseCtx::stra_sub_ticks(const char* stdCode)
{
	_engine->sub_tick(id(), stdCode);
	log_info("Market Data subscribed: %s", stdCode);
}

/*!
 * \brief 订阅委托明细数据实现
 * \param stdCode 标准合约代码
 * 
 * \details 通过UFT引擎订阅指定合约的委托明细数据，并记录订阅日志
 */
void UftStraBaseCtx::stra_sub_order_details(const char* stdCode)
{
	_engine->sub_order_detail(id(), stdCode);
	log_info("Order details subscribed: %s", stdCode);
}

/*!
 * \brief 订阅委托队列数据实现
 * \param stdCode 标准合约代码
 * 
 * \details 通过UFT引擎订阅指定合约的委托队列数据，并记录订阅日志
 */
void UftStraBaseCtx::stra_sub_order_queues(const char* stdCode)
{
	_engine->sub_order_queue(id(), stdCode);
	log_info("Order queues subscribed: %s", stdCode);
}

/*!
 * \brief 订阅成交明细数据实现
 * \param stdCode 标准合约代码
 * 
 * \details 通过UFT引擎订阅指定合约的成交明细数据，并记录订阅日志
 */
void UftStraBaseCtx::stra_sub_transactions(const char* stdCode)
{
	_engine->sub_transaction(id(), stdCode);
	log_info("Transactions subscribed: %s", stdCode);
}

/*!
 * \brief 输出信息级别日志实现
 * \param message 日志消息
 * 
 * \details 使用WTSLogger输出策略信息级别日志
 */
void UftStraBaseCtx::stra_log_info(const char* message)
{
	WTSLogger::log_dyn_raw("strategy", _name.c_str(), LL_INFO, message);
}

/*!
 * \brief 输出调试级别日志实现
 * \param message 日志消息
 * 
 * \details 使用WTSLogger输出策略调试级别日志
 */
void UftStraBaseCtx::stra_log_debug(const char* message)
{
	WTSLogger::log_dyn_raw("strategy", _name.c_str(), LL_DEBUG, message);
}

/*!
 * \brief 输出错误级别日志实现
 * \param message 日志消息
 * 
 * \details 使用WTSLogger输出策略错误级别日志
 */
void UftStraBaseCtx::stra_log_error(const char* message)
{
	WTSLogger::log_dyn_raw("strategy", _name.c_str(), LL_ERROR, message);
}

/*!
 * \brief 成交回报通知实现
 * \param localid 本地订单ID
 * \param stdCode 标准合约代码
 * \param isLong 是否多头方向
 * \param offset 开平仓标志
 * \param vol 成交数量
 * \param price 成交价格
 * 
 * \details 默认空实现，派生类需要重写此方法处理成交回报
 */
void UftStraBaseCtx::on_trade(uint32_t localid, const char* stdCode, bool isLong, uint32_t offset, double vol, double price)
{

}

/*!
 * \brief 订单状态通知实现
 * \param localid 本地订单ID
 * \param stdCode 标准合约代码
 * \param isLong 是否多头方向
 * \param offset 开平仓标志
 * \param totalQty 订单总量
 * \param leftQty 剩余数量
 * \param price 订单价格
 * \param isCanceled 是否已撤销
 * 
 * \details 默认空实现，派生类需要重写此方法处理订单状态变化
 */
void UftStraBaseCtx::on_order(uint32_t localid, const char* stdCode, bool isLong, uint32_t offset, double totalQty, double leftQty, double price, bool isCanceled /* = false */)
{

}

/*!
 * \brief 交易通道就绪通知实现
 * 
 * \details 默认空实现，派生类可以重写此方法处理交易通道就绪事件
 */
void UftStraBaseCtx::on_channel_ready()
{

}

/*!
 * \brief 交易通道断开通知实现
 * 
 * \details 默认空实现，派生类可以重写此方法处理交易通道断开事件
 */
void UftStraBaseCtx::on_channel_lost()
{

}

/*!
 * \brief 委托结果通知实现
 * \param localid 本地订单ID
 * \param stdCode 标准合约代码
 * \param bSuccess 委托是否成功
 * \param message 错误信息（如果失败）
 * 
 * \details 默认空实现，派生类需要重写此方法处理委托结果通知
 */
void UftStraBaseCtx::on_entrust(uint32_t localid, const char* stdCode, bool bSuccess, const char* message)
{

}

/*!
 * \brief 持仓变化通知实现
 * \param stdCode 标准合约代码
 * \param isLong 是否多头持仓
 * \param prevol 昨仓数量
 * \param preavail 昨仓可用数量
 * \param newvol 今仓数量
 * \param newavail 今仓可用数量
 * \param tradingday 交易日
 * 
 * \details 默认空实现，派生类需要重写此方法处理持仓变化通知
 */
void UftStraBaseCtx::on_position(const char* stdCode, bool isLong, double prevol, double preavail, double newvol, double newavail, uint32_t tradingday)
{

}

/*!
 * \brief 获取持仓数量实现
 * \param stdCode 标准合约代码
 * \param bOnlyValid 是否只获取有效持仓
 * \param iFlag 持仓标志（此参数未使用）
 * \return double 持仓数量
 * 
 * \details 通过交易适配器获取指定合约的持仓数量
 */
double UftStraBaseCtx::stra_get_position(const char* stdCode, bool bOnlyValid /* = false */, int32_t iFlag /* = 0 */)
{
	return _trader->getPosition(stdCode, bOnlyValid);
}

/*!
 * \brief 枚举持仓实现
 * \param stdCode 标准合约代码
 * \return double 持仓数量
 * 
 * \details 通过交易适配器枚举指定合约的持仓信息
 */
double UftStraBaseCtx::stra_enum_position(const char* stdCode)
{
	return _trader->enumPosition(stdCode);
}

/*!
 * \brief 获取未完成订单数量实现
 * \param stdCode 标准合约代码
 * \return double 未完成订单数量
 * 
 * \details 通过交易适配器获取指定合约的未完成订单总数量
 */
double UftStraBaseCtx::stra_get_undone(const char* stdCode)
{
	return _trader->getUndoneQty(stdCode);
}

/*!
 * \brief 获取最新价格实现
 * \param stdCode 标准合约代码
 * \return double 最新价格
 * 
 * \details 通过UFT引擎获取指定合约的当前价格
 */
double UftStraBaseCtx::stra_get_price(const char* stdCode)
{
	return _engine->get_cur_price(stdCode);
}

/*!
 * \brief 获取当前交易日期实现
 * \return uint32_t 交易日期（格式：YYYYMMDD）
 * 
 * \details 通过UFT引擎获取当前交易日期
 */
uint32_t UftStraBaseCtx::stra_get_date()
{
	return _engine->get_date();
}

/*!
 * \brief 获取当前交易时间实现
 * \return uint32_t 交易时间（格式：HHMM）
 * 
 * \details 通过UFT引擎获取当前原始时间
 */
uint32_t UftStraBaseCtx::stra_get_time()
{
	return _engine->get_raw_time();
}

/*!
 * \brief 获取当前精确时间实现
 * \return uint32_t 精确时间（格式：HHMMSSsss）
 * 
 * \details 通过UFT引擎获取当前精确秒数
 */
uint32_t UftStraBaseCtx::stra_get_secs()
{
	return _engine->get_secs();
}

